﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using StructureMap;
using Randata.IoC;
using Randata.DataResolvers;
using System.Reflection;
using Randata.DataResolvers.Implementation;

namespace Randata
{
    public static class DataProvider
    {
        internal static Dictionary<Type, Object> Instances { get; private set; }

        static DataProvider()
        {
            ObjectFactory.Configure(x => x.AddRegistry<ResolversRegister>());
        }

        public static T Any<T>()
        {
            //DataResolver<T> resolver = ObjectFactory.GetInstance<DataResolver<T>>();
            //return resolver.Resolve();
            DataProvider.Instances = new Dictionary<Type, object>();
            return (T)Any(typeof(T));
        }

        internal static Object Any(Type type)
        {
            if (DataProvider.Instances.ContainsKey(type))
                return DataProvider.Instances[type];

            if (type.GetInterfaces().Where(x => x.Name == "IList").Count() > 0)
            {
                Type key = typeof(DataResolver<>).MakeGenericType(type);
                Object r = ObjectFactory.TryGetInstance(key);
                if (r == null)
                {
                    Type item = type.GetGenericArguments()[0];
                    Type value = typeof(ListDataResolver<>).MakeGenericType(item);
                    ObjectFactory.Configure(x => x.AddType(key, value));
                }
            }

            if (type.IsEnum)
            {
                Type key = typeof(DataResolver<>).MakeGenericType(type);
                Object r = ObjectFactory.TryGetInstance(key);
                if (r == null)
                {
                    Type value = typeof(EnumDataResolver<>).MakeGenericType(type);
                    ObjectFactory.Configure(x => x.AddType(key, value));
                }
            }

            Type baseType = typeof(DataResolver<>).MakeGenericType(type);

            Object resolver = ObjectFactory.TryGetInstance(baseType);

            if (resolver == null)
            {
                Type resolverType = typeof(CustomObjectDataResolver<>).MakeGenericType(type);
                resolver = resolverType.GetConstructor(Type.EmptyTypes).Invoke(new Object[] { });
            }

            BindingFlags bindingFlags = System.Reflection.BindingFlags.Instance
                | System.Reflection.BindingFlags.NonPublic;

            Object instance = resolver.GetType().GetMethod("Resolve", bindingFlags).Invoke(resolver, null);

            //_instances.Add(type, instance);

            return instance;
        }

    }
}
